package me.flyray.bsin.gateway.context;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import me.flyray.bsin.gateway.common.CommonConstants;
import me.flyray.bsin.gateway.utils.StringHelper;


/**
 * Created by bolei on 2017/9/8.
 */
public class BaseContextHandler {

    private static final ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>() {
        protected Map<String, Object> initialValue() {
            return new HashMap<String, Object>();
        }
    };

    public static void set(String key, Object value) {
        Map<String, Object> map = threadLocal.get();
        if (map == null) {
            map = new HashMap<String, Object>();
            threadLocal.set(map);
        }
        map.put(key, value);
    }

    public static Object get(String key) {
        Map<String, Object> map = threadLocal.get();
        if (map == null) {
            map = new HashMap<String, Object>();
            threadLocal.set(map);
        }
        return map.get(key);
    }

    public static String getToken() {
        Object value = get(CommonConstants.CONTEXT_KEY_TOKEN);
        return StringHelper.getObjectValue(value);
    }

    public static String getXId() {
        Object value = get(CommonConstants.CONTEXT_KEY_X_ID);
        return StringHelper.getObjectValue(value);
    }

    public static String getXName() {
        Object value = get(CommonConstants.CONTEXT_KEY_NAME);
        return StringHelper.getObjectValue(value);
    }

    public static String getNickname() {
        Object value = get(CommonConstants.CONTEXT_KEY_NICKNAME);
        return StringHelper.getObjectValue(value);
    }

    public static String getPlatformId() {
        Object value = get(CommonConstants.CONTEXT_KEY_PLATFORMID);
        return StringHelper.getObjectValue(value);
    }

    public static String getUserType() {
        Object value = get(CommonConstants.JWT_KEY_USER_TYPE);
        return StringHelper.getObjectValue(value);
    }


    public static void setNickname(String name) {
        set(CommonConstants.CONTEXT_KEY_NICKNAME, name);
    }

    public static void setXId(String XId) {
        set(CommonConstants.CONTEXT_KEY_X_ID, XId);
    }

    public static void setUserType(String userType) {
        set(CommonConstants.JWT_KEY_USER_TYPE, userType);
    }

    private static String returnObjectValue(Object value) {
        return value == null ? null : value.toString();
    }

    public static void remove() {
        threadLocal.remove();
    }

    public static void main(String[] args) {
        // 使用固定大小为1的线程池,说明上一个的线程属性会被下一个线程属性复用
        ExecutorService pool = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 20; i++) {
            Mythead mythead = new Mythead();
            pool.execute(mythead);
        }
    }

    private static class Mythead extends Thread {
        private static boolean flag = true;

        @Override
        public void run() {
            if (flag) {
                // 第一个线程set后,并没有进行remove
                // 而第二个线程由于某种原因没有进行set操作
                set("1", "session info." + this.getName());
                flag = false;
            }

            System.out.println(this.getName() + " 线程是 " + get("1"));
            //remove();
            // 但是由于ThreadLocal没有在线程处理结束时及时进行remove清理操作
            // 在高并发场景下,线程池中的线程属性会被下一个线程属性复用
        }
    }


}
